// (C) 2022 Intel Corporation. All rights reserved.
// Your use of Intel Corporation's design tools, logic functions and other 
// software and tools, and its AMPP partner logic functions, and any output 
// files from any of the foregoing (including device programming or simulation 
// files), and any associated documentation or information are expressly subject 
// to the terms and conditions of the Intel Program License Subscription 
// Agreement, Intel FPGA IP License Agreement, or other applicable 
// license agreement, including, without limitation, that your use is for the 
// sole purpose of programming logic devices manufactured by Intel and sold by 
// Intel or its authorized distributors.  Please refer to the applicable 
// agreement for further details.

module RJO_FlashCtrl
    #(
        parameter JUMPER_COUNT  = 6'd48 
   
    )


(
    input               Clock,                    //FPGA Primary Synchronous Clock
    input               Reset,                    //Synchronous Reset
    input               RSU_FlashBusy,
    input      [31: 0]  FlashRJCWrData,           //Write Data for writing CSR data into flash                   
    input      [31: 0]  FlashOpAddr,              //Address for flash write and read operation, reserved for UFM erase protection, default 0
    input      [ 5: 0]  FlashOpLen,               //Number of 32-bit words to do in write operation
    
    input               FlashOpRd,                //Starts a flash read if unlocked and ready
    input               FlashOpWr,                //Starts a flash write if unlocked and ready
    input               FlashOpEr,                //Starts a flash erase if unlocked and ready
    output              FlashRdBusy,
    output              FlashWrBusy,
    output              FlashEraseBusy,   
   
    output  reg         FlashRdSuccess,
    output  reg         FlashWrSuccess,
    output  reg         FlashEraseSuccess,	 
    output reg  [ 5: 0] ReadCnt, 
    output reg          FlashError,               //An error has occurred with the flash command,clear when next operation comes
    output reg  [5: 0]  WriteCnt,                 //Counter for tracking writes to flash
    output reg     [31:0]  UFMLdData ,
	 output reg	         loaddataen,
	 
    //expose flash ctrl&data avmm intf out
    output reg          CntlAddrReg,              //Registered control interface address
    output reg          CntlRdReg,                //Registered control interface read enable
    output reg [31: 0]  CntlWrDataReg,            //Registered control interface write data
    output reg          CntlWrReg,                //Registered control interface write enable
    input      [31: 0]  CntlRdData,      
    output reg [31: 0]  DataAddrReg,              //Registered data interface address
    output reg          DataRdReg,                //Registered data interface read enable
    output reg [31: 0]  DataWrDataReg,            //Registered data interface write data
    output reg          DataWrReg,                //Registered data interface write enable
    input      [31: 0]  DataRdData,               //Data interface read data
    input               DataWaitReq,              //Data interface wait request
    input               DataRdValid,              //Data interface read data valid
    output reg [ 6: 0]  DataBurstCntReg           //Registered data interface burst count for bus read


);

 
  //Internal Wires
 
  reg             CntlAddr;                 //Control interface address
  reg             CntlRd;                   //Control interface read enable
  reg     [31: 0] CntlWrData;               //Control interface write data
  reg             CntlWr;                   //Control interface write enable
  reg     [31: 0] DataAddr;                 //Data interface address
  reg             DataRd;                   //Data interface read enable
  reg     [31: 0] DataWrData;               //Data interface write data
  reg             DataWr;                   //Data interface write enable
  reg     [ 6: 0] DataBurstCnt;             //Data interface burst count for bus read
  reg             StoreControlVals;         //Store values from command module
  reg             NextFlashCmdAck;          //Computed next value
  reg             FlashErrorSet;            //Set to indicate an error happened
  reg             WritePrep;                //Prepare for a write operation
  reg             ReadPrep;                 //Prepare for a read operation
  reg             WriteDone;                //Write of a 32-bit word is complete
  reg             ReadDone ;                //Read of a 32-bit word is complete
  //Internal Registers
  reg     [31: 0] FlashWrAddr;              //Address to actually write to the flash module
  reg     [31: 0] FlashRdAddr;
  reg             ControlIdle;              //Control module is indicating idle                 
  
  reg     [31: 0] Ufmdataread;
  reg             FlashCmdAck;
  
  reg              ControlRdOk;
  reg              ControlWrOk;
  reg              ControlErOk;   
  reg              ReadDone_FF;
  
   always @(posedge Clock)
  begin
    if(Reset)
      ReadDone_FF    <= 32'b0;
		else ReadDone_FF <= ReadDone;
  end
  
  //Register to control real address to write to flash
  always @(posedge Clock)
  begin
    if(Reset)
      FlashWrAddr    <= 32'b0;
    else if(WritePrep)
      FlashWrAddr    <= FlashOpAddr;
    else if(WriteDone)
      FlashWrAddr    <= FlashWrAddr + 32'd1;
    else
      FlashWrAddr    <= FlashWrAddr;  
  end
    //Register to control real address to read to CSR
  always @(posedge Clock)
  begin
    if(Reset)
      FlashRdAddr <= 32'b0;
    else if(ReadPrep)
      FlashRdAddr <= FlashOpAddr;
    else if(!ReadDone_FF&&ReadDone)
      FlashRdAddr <= FlashRdAddr + 32'd1;
    else
      FlashRdAddr <= FlashRdAddr;
  end
  //Count down the number of words to be written
  always @(posedge Clock)
  begin
    if(Reset)
      WriteCnt <= 6'b0;
    else if(WritePrep)
      WriteCnt <= FlashOpLen;
    else if(WriteDone & (WriteCnt != 6'b0))
      WriteCnt <= WriteCnt - 6'd1;
    else
      WriteCnt <= WriteCnt;
  end
  //Count down the number of words to be load
  always @(posedge Clock)
  begin
    if(Reset)
      ReadCnt <= 6'b0;
    else if(ReadPrep)
      ReadCnt <= FlashOpLen;
    else if(!ReadDone_FF&&ReadDone & (ReadCnt != 6'b0))
      ReadCnt <= ReadCnt - 6'd1;
    else
      ReadCnt <= ReadCnt;
  end

 
  //Store value from the control module when it is read
  always @(posedge Clock)
  begin
    if(Reset)
      begin
        ControlIdle    <= 1'b0;
        ControlWrOk    <= 1'b0;
        ControlRdOk    <= 1'b0;
        ControlErOk    <= 1'b0;
   
      end
      else if(NextFlashCmdAck)
      begin
        ControlIdle    <= 1'b0;
        ControlWrOk    <= 1'b0;
        ControlRdOk    <= 1'b0;
        ControlErOk    <= 1'b0;
   
      end
    else if(StoreControlVals)
      begin
        ControlIdle    <= (CntlRdData[1:0] == 2'b0);
        ControlRdOk    <= CntlRdData[2];
        ControlWrOk    <= CntlRdData[3];
        ControlErOk    <= CntlRdData[4];

      end
    else
      begin
        ControlIdle    <= ControlIdle;
        ControlRdOk    <= ControlRdOk;
        ControlWrOk    <= ControlWrOk;
        ControlErOk    <= ControlErOk;

      end    
  end
 
  
		
		
		
  //State machine to control flash interface
  parameter [5:0]
    YFI_READ_SET          =  0,
    YFI_READ_LAT          =  1,
    YFI_READ_STR          =  2,
    YFI_READ_VAL          =  3,
    
    YFI_E_PREP        =  4,
    YFI_E_CLR_SWP     =  5,
    YFI_E_SET_SEL     =  6,
    YFI_E_WAIT_BUSY_SET  =  7,
    YFI_E_WAIT_BUSY_LAT  =  8,
    YFI_E_WAIT_BUSY_STR  =  9,
    YFI_E_WAIT_BUSY      = 10,
    YFI_E_WAIT_IDLE      = 11,
    YFI_E_CHK_ERROR      = 12,
    YFI_E_SET_SWP        = 13,
    
    YFI_W_PREP           = 14,
    YFI_W_CLR_SWP        = 15,
    YFI_W_LOAD_WORD      = 16,
    YFI_W_WRITE_WORD     = 17,
    YFI_W_WAIT_WAIT_REQ_H = 18,
    YFI_W_WAIT_WAIT_REQ_L = 19,
    YFI_W_WAIT_IDLE_PREP  = 20,
    YFI_W_WAIT_IDLE_STR   = 21,
    YFI_W_WAIT_IDLE       = 22,
    YFI_W_CHK_ERROR       = 23,
    YFI_W_SET_SWP         = 24,
   
   YFI_R_PREP            = 25,
   YFI_R_READ_WORD       = 26,
   YFI_R_VAL_H           = 27,
   YFI_R_VAL_L           = 28,
   YFI_R_WAIT_IDLE_PREP  = 29,
   YFI_R_WAIT_IDLE_STR   = 30,
   YFI_R_WAIT_IDLE       = 31,
   YFI_R_CHK_ERROR       = 32,
	YFI_R_SET_SWP         = 33,
   YFI_READ_IDLE	 = 34;	
    
  reg [5:0] CurrentState, NextState;
  
  always @(posedge Clock)
  begin
    if(Reset)
      CurrentState <= YFI_READ_SET;
    else
      CurrentState <= NextState;
  end
  
  //Next state logic
  always @(CurrentState or ControlIdle or FlashOpRd or FlashOpWr or FlashOpEr or WriteCnt or DataWaitReq or DataRdValid or RSU_FlashBusy or ReadCnt)
  begin
    case(CurrentState)
    
      /////////////////////////////////////////////////////////////////////////////
      // Basic loop to monitor status
      /////////////////////////////////////////////////////////////////////////////

      YFI_READ_SET :
        //Set Address and Read Command
        NextState = YFI_READ_LAT;
        
      YFI_READ_LAT :
        //At this state, avmm_csr_address and avmm_csr_read are set
        NextState = YFI_READ_STR;
        
      YFI_READ_STR :
        //Set StoreControlVals in order to store data read from control register
        NextState = YFI_READ_VAL;
        
      YFI_READ_VAL :
	NextState = YFI_READ_IDLE;
         // At this state, we get the value that read from Control register, use
         //this value to decide whether need erase or write
         // at the same time ,we clear flash busy signal
	    
      YFI_READ_IDLE:	    
        begin
          if(!RSU_FlashBusy & ControlIdle & FlashOpWr )
            //We are OK to start a write
            NextState = YFI_W_PREP;
          else if(!RSU_FlashBusy & ControlIdle & FlashOpEr )
            //We are OK to start a erase
            NextState = YFI_E_PREP;
          else if(!RSU_FlashBusy & ControlIdle & FlashOpRd)
            //We are OK to start a read
            NextState = YFI_R_PREP;
          else
            NextState = YFI_READ_IDLE;
        end
      
      /////////////////////////////////////////////////////////////////////////////
      // Erase states
      /////////////////////////////////////////////////////////////////////////////
        
      YFI_E_PREP :
        //Setup erase registers and start，Indicate that we will start to do an operation , need to assert flash busy at next clock
        begin 
         if(RSU_FlashBusy) begin
           NextState = YFI_E_PREP;
         end
         else NextState = YFI_E_CLR_SWP;
        end 
      YFI_E_CLR_SWP :
        //Flash busy asserted
        //Clear the write protect bit of sector ID1 and Setup write command and CntlAddr
        begin 
         if(RSU_FlashBusy) begin
            NextState = YFI_E_CLR_SWP;
         end
         else NextState = YFI_E_SET_SEL;
        end 
      YFI_E_SET_SEL :
        //avmm_csr_writedata = 32'hFF7FFFFF take effect;
        //Set CntlWrData sector erase address
       begin 
        if(RSU_FlashBusy) begin
           NextState = YFI_E_SET_SEL;
        end
          else NextState = YFI_E_WAIT_BUSY_SET;
        end 
      YFI_E_WAIT_BUSY_SET :
        //avmm_csr_writedata = 32'hFF1FFFFF take effect; Erase start;
        //set status register address and read command
        begin 
          if(RSU_FlashBusy) begin
            NextState = YFI_E_WAIT_BUSY_SET;
           end
        else NextState = YFI_E_WAIT_BUSY_LAT;
        end 
      YFI_E_WAIT_BUSY_LAT :
        //avmm_csr_read,avmm_csr_address take effect
        //data avmm output on this clock
       begin 
         if(RSU_FlashBusy) begin
          NextState = YFI_E_WAIT_BUSY_LAT;
         end
        else NextState = YFI_E_WAIT_BUSY_STR;
        end 
      YFI_E_WAIT_BUSY_STR :
        //Set StoreControlVals to store avmm output
      begin 
        if(RSU_FlashBusy) begin
          NextState = YFI_E_WAIT_BUSY_STR;
        end
        else NextState = YFI_E_WAIT_BUSY;
       end  
      YFI_E_WAIT_BUSY :
      begin 
        if(RSU_FlashBusy) begin
        NextState = YFI_E_WAIT_BUSY;
        end
        else NextState = YFI_E_WAIT_IDLE;
       end 
      YFI_E_WAIT_IDLE :
        //4 clock after erase start,
        //if operation finish, go to next status
        begin
          if (RSU_FlashBusy) begin
          NextState = YFI_E_WAIT_IDLE;
          end
          else if(ControlIdle)
            //Erase is done go get status
            NextState = YFI_E_CHK_ERROR;
          else
            NextState = YFI_E_WAIT_IDLE;
        end
      
      YFI_E_CHK_ERROR :
        //Store the state of the failure bit
       begin 
        if(RSU_FlashBusy) begin
           NextState = YFI_E_CHK_ERROR;
        end
        else NextState = YFI_E_SET_SWP;
      end 
      YFI_E_SET_SWP :
        //Reset write protection, CntlWrData  <= 32'hFFFFFFFF;
        //avmm_csr_writedata = 32'hFFFFFFFF; will take effect at next status
       begin 
        if(RSU_FlashBusy) begin
           NextState = YFI_E_SET_SWP;
        end
        else NextState = YFI_READ_SET;
       end 
  
        
      /////////////////////////////////////////////////////////////////////////////
      // Write states
      /////////////////////////////////////////////////////////////////////////////
        
      YFI_W_PREP :
        //Setup write registers and start，Indicate that we will start to do a write operation , need to assert flash busy at next clock
       // Set WritePrep to get prepared for data address
       begin 
        if(RSU_FlashBusy) begin
           NextState = YFI_W_PREP;
        end
        else
           NextState = YFI_W_CLR_SWP;
        end 
      YFI_W_CLR_SWP :
        //Clear the write protect bits and move on
       begin 
        if(RSU_FlashBusy) begin
           NextState = YFI_W_CLR_SWP;
        end
        else
           NextState = YFI_W_LOAD_WORD;
        end 
      YFI_W_LOAD_WORD :
        //Let the RAM get valid data out
        begin 
        if(RSU_FlashBusy) begin
           NextState = YFI_W_LOAD_WORD;
        end
        else
           NextState = YFI_W_WRITE_WORD;
        end 
      YFI_W_WRITE_WORD :
        //Commit the word to a write
        begin 
        if(RSU_FlashBusy) begin
           NextState = YFI_W_WRITE_WORD;
        end
        else
        NextState = YFI_W_WAIT_WAIT_REQ_H;
        end 
      YFI_W_WAIT_WAIT_REQ_H :
        begin
          if(RSU_FlashBusy) begin
           NextState = YFI_W_WAIT_WAIT_REQ_H;
          end
          else if(DataWaitReq)
            //Wait until we see that the module has started the write
            NextState = YFI_W_WAIT_WAIT_REQ_L;
           else
            NextState = YFI_W_WAIT_WAIT_REQ_H;
        end
      
      YFI_W_WAIT_WAIT_REQ_L :
        begin
          if(RSU_FlashBusy) begin
           NextState = YFI_W_WAIT_WAIT_REQ_L;
          end
          else if(!DataWaitReq)
            //Wait until we see that the module has finished the write
            NextState = YFI_W_WAIT_IDLE_PREP;
          else
            NextState = YFI_W_WAIT_WAIT_REQ_L;
        end
      
      YFI_W_WAIT_IDLE_PREP :
        //Send a read to status register
         if(RSU_FlashBusy) begin
           NextState = YFI_W_WAIT_IDLE_PREP;
          end
          else
        NextState = YFI_W_WAIT_IDLE_STR;
        
      YFI_W_WAIT_IDLE_STR :
        //Store the result to get real data for next clock's usage of it
           if(RSU_FlashBusy) begin
           NextState = YFI_W_WAIT_IDLE_STR;
          end
          else
        NextState = YFI_W_WAIT_IDLE;
        
      YFI_W_WAIT_IDLE :
        begin
           if(RSU_FlashBusy) begin
           NextState = YFI_W_WAIT_IDLE;
          end
          else
          if(ControlIdle)
            //Write is done go get status
            NextState = YFI_W_CHK_ERROR;
          else
            NextState = YFI_W_WAIT_IDLE;
        end
      
      YFI_W_CHK_ERROR :
        begin
           if(RSU_FlashBusy) begin
           NextState = YFI_W_CHK_ERROR;
          end
          else
          if(WriteCnt > 6'd1)
            //More words to write
            NextState = YFI_W_LOAD_WORD;
          else
            NextState = YFI_W_SET_SWP;
        end
      
      YFI_W_SET_SWP :
        //Enable the write protect bits
       begin 
          if(RSU_FlashBusy) begin
           NextState = YFI_W_SET_SWP;
          end
          else
        NextState = YFI_READ_SET;
        end 
      //UFM read states
    YFI_R_PREP: 
    //Setup read registers and start
         begin 
          if(RSU_FlashBusy) begin
           NextState = YFI_R_PREP;
          end
          else
            NextState = YFI_R_READ_WORD;
          end 
    YFI_R_READ_WORD:
         begin 
          if(RSU_FlashBusy) begin
           NextState = YFI_R_READ_WORD;
          end
          else
            NextState = YFI_R_VAL_H;
          end 
    YFI_R_VAL_H:  
        begin
          if(RSU_FlashBusy) begin
           NextState = YFI_R_VAL_H;
          end
          else if (DataRdValid)
               NextState = YFI_R_VAL_L;
          else 
               NextState = YFI_R_VAL_H;
          end
    YFI_R_VAL_L:          
        begin
        if(RSU_FlashBusy) begin
           NextState = YFI_R_VAL_L;
          end
          else if (!DataRdValid) 
               NextState = YFI_R_WAIT_IDLE_PREP;
          else   
               NextState = YFI_R_VAL_L;
        end
   YFI_R_WAIT_IDLE_PREP: 
         begin 
          if(RSU_FlashBusy) begin
           NextState = YFI_R_WAIT_IDLE_PREP;
          end
          else
            NextState = YFI_R_WAIT_IDLE_STR;
          end 
   YFI_R_WAIT_IDLE_STR:
          begin 
          if(RSU_FlashBusy) begin
           NextState = YFI_R_WAIT_IDLE_STR;
          end
          else
            NextState = YFI_R_WAIT_IDLE;
          end 
   YFI_R_WAIT_IDLE: 
       begin
          if(RSU_FlashBusy) begin
           NextState = YFI_R_WAIT_IDLE;
          end
          else if(ControlIdle)
            //Read is done go get status
              NextState = YFI_R_CHK_ERROR;
          else
            NextState = YFI_R_WAIT_IDLE;
        end
 
   YFI_R_CHK_ERROR:
           
     begin
      if(RSU_FlashBusy) begin
           NextState = YFI_R_CHK_ERROR;
          end
      else if(ReadCnt > 6'd1)
            //More words to write
            NextState = YFI_R_READ_WORD;
      else
            NextState = YFI_R_SET_SWP;
				
      end
	YFI_R_SET_SWP :
        //Reset write protection, CntlWrData  <= 32'hFFFFFFFF;
        //avmm_csr_writedata = 32'hFFFFFFFF; will take effect at next status
       begin 
        if(RSU_FlashBusy) begin
           NextState = YFI_R_SET_SWP;
        end
        else NextState = YFI_READ_SET;
       end 
  
  
      default:
        begin
          NextState = YFI_READ_SET;
        end
    endcase
  end
  
  //Decode state for control signals
  always @(CurrentState or ControlErOk or FlashWrAddr or ControlWrOk or FlashRJCWrData or FlashRdAddr or DataRdData or ControlRdOk)
  begin
    //Default to not asserted
    CntlAddr          = 1'b0;
    CntlRd            = 1'b0;
    CntlWrData        = 32'b0;
    CntlWr            = 1'b0;
    DataAddr          = 17'b0;
    DataRd            = 1'b0;
    DataWrData        = 32'b0;
    DataWr            = 1'b0;
    DataBurstCnt      = 7'b0;
    
    StoreControlVals  = 1'b0;
    NextFlashCmdAck   = 1'b0;
  
    FlashErrorSet     = 1'b0;
    WritePrep         = 1'b0;
    WriteDone         = 1'b0;
    ReadDone          = 1'b0;
    Ufmdataread       = 32'b0;
    ReadPrep          = 1'b0;
	 loaddataen        = 1'b0;

    case (CurrentState)

      /////////////////////////////////////////////////////////////////////////////
      // Basic loop to monitor status
      /////////////////////////////////////////////////////////////////////////////

      YFI_READ_SET :
        begin
          CntlAddr              = 1'b0;                      //Read status register
          CntlRd                = 1'b1;                      //Do the read
        end
        
      YFI_READ_LAT :
        begin
          CntlAddr              = 1'b0;                      //Read status register
          CntlRd                = 1'b1;                      //Do the read
        end
        
      YFI_READ_STR :
        begin
          CntlAddr              = 1'b0;                      //Read status register
          CntlRd                = 1'b1;                      //Do the read
          StoreControlVals      = 1'b1;                      //Data is now valid from previous read
        end
        
      YFI_READ_VAL :
        begin
          CntlAddr              = 1'b0;                      //Read status register
          CntlRd                = 1'b1;                      //Do the read
          StoreControlVals      = 1'b1;                      //Data is now valid from previous read
   
        end
      
      YFI_READ_IDLE :
	begin
	  CntlAddr              = 1'b0;                      //Read status register
          CntlRd                = 1'b0;                      //Do no read
          StoreControlVals      = 1'b1;                      //Data is now valid from previous read	
	end
      /////////////////////////////////////////////////////////////////////////////
      // Erase states
      /////////////////////////////////////////////////////////////////////////////
        
      YFI_E_PREP :
        begin
          NextFlashCmdAck       = 1'b1;                      //Clear the lock and command registers
        end

      YFI_E_CLR_SWP :
        begin
          CntlWr                = 1'b1;                      //Set to a write command
          CntlAddr              = 1'b1;                      //Write control register
          CntlWrData            = 32'hFF7FFFFF;              //Clear write protection for CFM1 (Image2)
        end                                                   //32'hFEFFFFFF clear ID2

      YFI_E_SET_SEL :
        begin
          CntlWr                = 1'b1;                      //Set to a write command
          CntlAddr              = 1'b1;                      //Write control register
          CntlWrData            = 32'hFF1FFFFF;              //Clear write protection for CFM1 and set CFM1 sector erase ID4
        end                                                   //erase ID2:010 32'hFEAFFFFF 

      YFI_E_WAIT_BUSY_SET :
        begin
          CntlAddr              = 1'b0;                      //Read status register
          CntlRd                = 1'b1;                      //Do the read
        end
        
      YFI_E_WAIT_BUSY_LAT :
        begin
          CntlAddr              = 1'b0;                      //Read status register
          CntlRd                = 1'b1;                      //Do the read
        end
        
      YFI_E_WAIT_BUSY_STR :
        begin
          CntlAddr              = 1'b0;                      //Read status register
          CntlRd                = 1'b1;                      //Do the read
          StoreControlVals      =1'b1;                      //Data is now valid from previous read
        end
        
      YFI_E_WAIT_BUSY :
        begin
          CntlAddr              = 1'b0;                      //Read status register
          CntlRd                = 1'b1;                      //Do the read
          StoreControlVals      = 1'b1;                      //Data is now valid from previous read
        end
        
      YFI_E_WAIT_IDLE :
        begin
          CntlAddr              = 1'b0;                      //Read status register
          CntlRd                = 1'b1;                      //Do the read
          StoreControlVals      = 1'b1;                      //Data is now valid from previous read
        end
        
      YFI_E_CHK_ERROR :
        begin
          FlashErrorSet         = !ControlErOk;              //Store the state of the bit
        end
        
      YFI_E_SET_SWP :
        begin
          CntlWr                = 1'b1;                      //Set to a write command
          CntlAddr              = 1'b1;                      //Write control register
          CntlWrData            = 32'hFFFFFFFF;              //Reset write protection
        end

    

      /////////////////////////////////////////////////////////////////////////////
      // Write states
      /////////////////////////////////////////////////////////////////////////////
        
      YFI_W_PREP :
        begin
          NextFlashCmdAck       = 1'b1;                      //Clear the lock and command registers
          WritePrep             = 1'b1;                      //Prepare write registers
        end

      YFI_W_CLR_SWP :
        begin
          CntlWr                = 1'b1;                      //Set to a write command
          CntlAddr              = 1'b1;                      //Write control register
          CntlWrData            = 32'hFF7FFFFF;              //Clear write protection for CFM1 and CFM2 (ID3&4)
        end                                                   // Clear write protection for ID2&3: 32'hFCFFFFFF. Only used for M04

      YFI_W_LOAD_WORD :
        begin
          DataAddr              = FlashWrAddr;               //Get address set up early
          DataWrData            = FlashRJCWrData;                  //Get data set up early
          DataBurstCnt          = 7'b1;                      //Burst write is only for 1 item
        end

      YFI_W_WRITE_WORD :
        begin
          DataAddr              = FlashWrAddr;               //Get address set up early
          DataWrData            = FlashRJCWrData;                  //Get data set up early
          DataBurstCnt          = 7'b1;                      //Burst write is only for 1 item
          DataWr                = 1'b1;                      //Commit write
          CntlAddr              = 1'b0;                      //Read status register
          CntlRd                = 1'b1;                      //Do the read
        end

      YFI_W_WAIT_WAIT_REQ_H :
        begin
          DataAddr              = FlashWrAddr;               //Get address set up early
          DataWrData            = FlashRJCWrData;                  //Get data set up early
          DataBurstCnt          = 7'b1;                      //Burst write is only for 1 item
          DataWr                = 1'b1;                      //Commit write
          CntlAddr              = 1'b0;                      //Read status register
          CntlRd                = 1'b1;                      //Do the read
          StoreControlVals      = 1'b1;                      //Data is now valid from previous read
        end
        
      YFI_W_WAIT_WAIT_REQ_L :
        begin
          DataAddr              = FlashWrAddr;               //Get address set up early
          DataWrData            = FlashRJCWrData;                  //Get data set up early
          DataBurstCnt          = 7'b1;                      //Burst write is only for 1 item
          CntlAddr              = 1'b0;                      //Read status register
			 CntlRd                = 1'b1;                      //Do the read
          StoreControlVals      = 1'b1;                      //Data is now valid from previous read
        end
        
      YFI_W_WAIT_IDLE_PREP :
        begin
          CntlAddr              = 1'b0;                      //Read status register
          CntlRd                = 1'b1;                      //Do the read
          StoreControlVals      = 1'b1;                      //Data is now valid from previous read
        end
        
      YFI_W_WAIT_IDLE_STR :
        begin
          CntlAddr              = 1'b0;                      //Read status register
          CntlRd                = 1'b1;                      //Do the read
          StoreControlVals      = 1'b1;                      //Data is now valid from previous read
        end
        
      YFI_W_WAIT_IDLE :
        begin
          CntlAddr              = 1'b0;                      //Read status register
          CntlRd                = 1'b1;                      //Do the read
          StoreControlVals      = 1'b1;                      //Data is now valid from previous read
   
        end                                                   
                                                              
        
      YFI_W_CHK_ERROR :
        begin
          FlashErrorSet         = !ControlWrOk;              //Store the state of the bit
          WriteDone             = 1'b1; 
        end                                                  
        
      YFI_W_SET_SWP :
        begin
          CntlWr                = 1'b1;                      //Set to a write command
          CntlAddr              = 1'b1;                      //Write control register
          CntlWrData            = 32'hFFFFFFFF;              //Reset write protection
        end
      
   /////////////////////////////////////
   //ufm read states
   /////////////////////////////////////

     YFI_R_PREP:             
      begin
       NextFlashCmdAck       = 1'b1;
       ReadPrep              = 1'b1;
      end
      
     YFI_R_READ_WORD:
      begin
        DataAddr              = FlashRdAddr;
        DataBurstCnt          = 7'b1;
        DataRd                = 1'b1;                       //Set read operation 
        CntlAddr              = 1'b0;                      //Read status register
        CntlRd                = 1'b1;       
      end
      
      YFI_R_VAL_H:
        begin
        DataAddr              = FlashRdAddr;
        DataBurstCnt          = 7'b1;
        DataRd                = 1'b1;
        CntlAddr              = 1'b0;                      
        CntlRd                = 1'b1;  
        StoreControlVals      = 1'b1;
        Ufmdataread           = DataRdData;                //Store UFM data into Ufmdataread
      end
      
     YFI_R_VAL_L:            
      begin
        DataAddr              = FlashRdAddr;
        DataBurstCnt          = 7'b1;
        CntlAddr              = 1'b0;                      //Read status register
        CntlRd                = 1'b1;  
        StoreControlVals      = 1'b1;
		  loaddataen            = 1'b1;
		
      end
      
     YFI_R_WAIT_IDLE_PREP:   
       begin
        CntlAddr              = 1'b0;                      //Read status register
          CntlRd                = 1'b1;                      //Do the read
          StoreControlVals      = 1'b1;                      //Data is now valid from previous read

      end

     YFI_R_WAIT_IDLE_STR:
      begin
        CntlAddr              = 1'b0;                      //Read status register
          CntlRd                = 1'b1;                      //Do the read
          StoreControlVals      = 1'b1; 
      end

     YFI_R_WAIT_IDLE:      
      begin
        CntlAddr              = 1'b0;                      //Read status register
          CntlRd                = 1'b1;                      //Do the read
          StoreControlVals      = 1'b1; 
     
      end

     YFI_R_CHK_ERROR:
      begin
        FlashErrorSet         = !ControlRdOk;
         ReadDone             = 1'b1;
      end      
      YFI_R_SET_SWP:
    	
		begin
          CntlAddr              = 1'b0;                      //Read status register
          CntlRd                = 1'b1;                      //Do the read
      end
    endcase
  end
      
  //Register the inputs to the module to investigate timing issues
  always @(posedge Clock)
  begin
    if(Reset)
      begin
        CntlAddrReg     <= 1'b0;
        CntlRdReg       <= 1'b0;
        CntlWrDataReg   <= 32'b0;
        CntlWrReg       <= 1'b0;
        DataAddrReg     <= 32'b0;
        DataWrDataReg   <= 32'b0;
        DataBurstCntReg <= 7'b0;
        DataWrReg       <= 1'b0;
        DataRdReg       <= 1'b0;
      end
    else
      begin
        CntlAddrReg     <= CntlAddr;
        CntlRdReg       <= CntlRd;
        CntlWrDataReg   <= CntlWrData;
        CntlWrReg       <= CntlWr;
        DataAddrReg     <= DataAddr;
        DataWrDataReg   <= DataWrData;
        DataBurstCntReg <= DataBurstCnt;
        DataWrReg       <= DataWr;
        DataRdReg       <= DataRd;
      end
  end

  //Register decoded outputs
  always @(posedge Clock)
  begin
    if(Reset)
      begin
        FlashCmdAck <= 1'b0;
      end
    else
      begin
        FlashCmdAck <= NextFlashCmdAck;
      end
  end
  
 
  //Register output for error indicator
  always @(posedge Clock)
  begin
    if(Reset)
      FlashError <= 1'b0;
    else if(NextFlashCmdAck)
      FlashError <= 1'b0;
    else if(FlashErrorSet)
      FlashError <= 1'b1;
    else
      FlashError <= FlashError;
  end
  
always @(posedge Clock)
  begin
    if(Reset)
      UFMLdData <= 32'hFFFFFFFF;
      
    else if(DataRdValid) // if data read out of flash 
      UFMLdData <= Ufmdataread;
		
    else
      UFMLdData <= UFMLdData;
  end

  
 assign FlashEraseBusy    = (CurrentState >= YFI_E_PREP) && (CurrentState <= YFI_E_SET_SWP);
  assign FlashWrBusy       = (CurrentState >= YFI_W_PREP) && (CurrentState <= YFI_W_SET_SWP);
  assign FlashRdBusy       = (CurrentState >= YFI_R_PREP) && (CurrentState <= YFI_R_SET_SWP);
 
 
 always @(posedge Clock)
  begin
    if(Reset)
      begin
        FlashWrSuccess       <= 1'b0;
        FlashRdSuccess       <= 1'b0;
        FlashEraseSuccess    <= 1'b0;
      end
		else if((CurrentState == YFI_E_PREP)||(CurrentState ==YFI_W_PREP))
      begin

        FlashEraseSuccess    <= 1'b0;
		  FlashWrSuccess       <= 1'b0;
   
      end
	
		else if(CurrentState == YFI_R_PREP)
      begin

        FlashRdSuccess    <= 1'b0;
   
      end
		
		else if((CurrentState == YFI_W_SET_SWP) && ControlWrOk)
		begin
		  FlashWrSuccess       <= 1'b1;

		end
		else if((CurrentState == YFI_R_SET_SWP) && ControlRdOk)
      begin
   
        FlashRdSuccess       <= 1'b1;
 
   
      end
		else if((CurrentState == YFI_E_SET_SWP) && ControlErOk)
      begin

        FlashEraseSuccess    <= 1'b1;
   
      end
		 else begin
        FlashWrSuccess    <= FlashWrSuccess;
        FlashRdSuccess    <= FlashRdSuccess;
        FlashEraseSuccess    <= FlashEraseSuccess;
      

      end    
  end
		
endmodule
